/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package runebound.ui.mapa;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;
import runebound.basedatos.Camino;
import runebound.basedatos.RBConexion;
import runebound.basedatos.Rio;
import runebound.manejadores.RBControladorJuego;
import runebound.modelo.Ciudad;
import runebound.modelo.Gema;
import runebound.modelo.heores.Heroe;

/**
 *
 * @author Miguel (alakat@gmail.com)
 */
public class RBMapaPanel extends JPanel {

    public static final int XLEN = 13;
    public static final int YLEN = 14;

    private TileMapa[][] mapa = new TileMapa[XLEN][YLEN];
    private List<TileMapa> tilesAccesibles;
    private TileMapa tileActivo;

    public RBMapaPanel() {

        this.tilesAccesibles=new ArrayList<>();
        try {
            for (int i = 0; i < XLEN; i++) {
                for (int j = 0; j < YLEN; j++) {
                    this.mapa[i][j] = RBConexion.getInstance().getTile(i, j);
                }
            }

            List<Rio> rios = RBConexion.getInstance().getRios();
            for (Rio rio : rios) {
                this.mapa[rio.getI()][rio.getJ()].setConector(rio);
            }

            List<Camino> caminos = RBConexion.getInstance().getCaminos();
            for (Camino camino : caminos) {
                this.mapa[camino.getI()][camino.getJ()].setConector(camino);
            }

            List<Gema> gemas = RBConexion.getInstance().getGemas();
            for (Gema gema : gemas) {
                this.mapa[gema.getI()][gema.getJ()].setGema(gema);
            }

            List<Ciudad> ciudades = RBConexion.getInstance().getCiudades();
            for (Ciudad ciudad : ciudades) {
                this.mapa[ciudad.getI()][ciudad.getJ()].setCiudad(ciudad);
                ciudad.setTilemap(this.mapa[ciudad.getI()][ciudad.getJ()]);
            }
            
            
            
        } catch (Exception ex) {
            System.err.println(ex);
        }
        this.addMouseListener(new MouseMapaListener(this));
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
//        int XLEN_TOT = RBMapaPanel.XLEN*TileMapa.XLEN;
        try {
            int YLEN_TOT = RBMapaPanel.YLEN * TileMapa.getYLEN();
            int addy = 0;
            for (int i = 0; i < this.mapa.length; i++) {

                for (int j = 0; j < this.mapa[0].length; j++) {
                    TileMapa tm = this.mapa[i][j];
                    Point p = this.getTilePoint(i, j, YLEN_TOT, addy);
                    Graphics g1 = g.create(p.x,
                            p.y, TileMapa.getXLEN(), TileMapa.getYLEN());
                    tm.paint(g1);
                }
                addy++;
                addy = addy % 2;
            }
        }catch(Exception ex){
            System.err.println(ex);
        }
    }

    public TileMapa[][] getMapa() {
        return mapa;
    }

    /**
     *
     * @param i
     * @param j
     * @param ylen_tot
     * @param addy
     * @return
     */
    public Point getTilePoint(int i, int j, int ylen_tot, int addy) {
        int x = (i * ((3 * TileMapa.getXLEN()) / 4));
        int y = ylen_tot - ((j * TileMapa.getYLEN()) - (addy * (TileMapa.getYLEN() / 2))) - YLEN;
        return new Point(x, y);
    }

    public TileMapa getTile(Point pEvent) {
        int YLEN_TOT = RBMapaPanel.YLEN * TileMapa.getYLEN();
        int addy = 0;
        System.out.println("Evento:" + pEvent);
        for (int i = 0; i < this.mapa.length; i++) {
            for (int j = 0; j < this.mapa[0].length; j++) {
                Point pTile = this.getTilePoint(i, j, YLEN_TOT, addy);
                Rectangle r = new Rectangle(pTile, new Dimension(TileMapa.getXLEN(), TileMapa.getYLEN()));

                if (r.contains(pEvent)) {
                    return this.mapa[i][j];
                }

            }
            addy++;
            addy = addy % 2;
        }
        return null;
    }

    
    /***
     * Actualiza la distribución de tiles del mapa que son acesibles para el movimiento
     * 
     * @param dadoSeleccionado 
     */
    public void setNuevoTerrenoAccesible(Terreno[] dadoSeleccionado) {
        for (TileMapa tile : this.tilesAccesibles) {
            tile.setEstado(EstadoTileMapa.ESPERA);
        }
        this.tilesAccesibles.clear();
        TileMapa centro = this.tileActivo;
        List<TileMapa> vecinos = getVecinosPorTile(centro);
        for (TileMapa vecino : vecinos) {
            boolean accesible = false;
            for (int i = 0; i < dadoSeleccionado.length; i++) {
                if(vecino.isTerrenoAccesible(dadoSeleccionado[i]))
                    accesible=true;
            }
            if (accesible) {
                vecino.setEstado(EstadoTileMapa.TILE_ACESIBLE);
                this.tilesAccesibles.add(vecino);
            }   
        }
        this.repaint();
        
    }

    /**
     * Obtiene los vecinos de un centro
     * @param centro
     * @return 
     */
    public List<TileMapa> getVecinosPorTile(TileMapa centro) {
        List<TileMapa> vecinos = new ArrayList<>();
        int[][] mascara;
        if(centro.getX()%2==0){
            /*
            * Par
            */
            mascara=new int[][]{{0,1},{1,1},{1,0},{0,-1},{-1,0},{-1,1}};
        }else{
            /*
            * impar
            */
            mascara=new int[][]{{0,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0}};
        }
        int[][] indices = new int[6][2];
        for (int i = 0; i < mascara.length; i++) {
            indices[i][0]=mascara[i][0]+centro.getX();
            indices[i][1]=mascara[i][1]+centro.getY();
        }
        for (int i = 0; i < indices.length; i++) {
            if(indices[i][0]<this.mapa.length &&
                    indices[i][1]<this.mapa[0].length &&
                    indices[i][0]>=0 &&
                    indices[i][1]>=0){
                vecinos.add(this.mapa[indices[i][0]][indices[i][1]]);
            }
            
        }
        return vecinos;
    }

    /**
     * Tile activa en este momento
     * @return 
     */
    public TileMapa getTileActivo() {
        return tileActivo;
    }

    /**
     * asigna el tile activo enel movimento
     * @param tileActivo 
     */
    public void setTileActivo(TileMapa tileActivo) {
        if(this.tileActivo!=null){
            this.tileActivo.setEstado(EstadoTileMapa.ESPERA);
        }
        for (TileMapa tile: this.tilesAccesibles) {
            tile.setEstado(EstadoTileMapa.ESPERA);
        }
        this.tileActivo = tileActivo;
    }

    /**
     * Devuelve el tile de una coordenada
     * @param x
     * @param y
     * @return 
     */
    public TileMapa getTile(int x, int y) {
        return this.mapa[x][y];
    }
    
    
    

    
}
